package service

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"choujiang/common/db"
	"choujiang/common/models"
	"choujiang/common/utils"
	"math/rand"
	"net/http"
	"net/url"
	"strconv"
	"time"
	"github.com/go-redis/redis"
	"choujiang/common/consts"
)

const (
	HOMEPAGE_ALERT_KEY = "BoxKey::leyouboxhomepagealert" //Redis首页弹窗缓存的key值
	FORM_ID_KEY        = "BoxKey::leyouboxformid"        //用户通知表单ID缓存
	FREE_LOTTERY_GOODS = "BoxKey::free_lottery_goods_"   //免费抽奖记录
)

type PrepareId struct {
	Id   int64  `json:"id"`
	Code string `json:"code"`
}

type CouponLog struct {
	GoodsId      int64               `json:"goods_id"`
	Cover        string              `json:"cover"`
	GoodsName    string              `json:"goods_name"`
	CouponStatus int64               `json:"coupon_status"`
	LimitPeople  int64               `json:"limit_people"`
	CurPeople    int64               `json:"cur_people"`
	MyCouponNum  int64               `json:"my_coupon_num"` //我参与的奖券数量
	MyCoupon     []model.GoodsCoupon `json:"my_coupon"`     //我参与的全部奖券
	MyWinCoupon  []model.GoodsCoupon `json:"my_win_coupon"` //我中奖的奖券
	IsWin        bool                `json:"is_win"`        //是否中奖
}

type CouponMember struct {
	Nickname   string `json:"nickname"`
	HeadImgUrl string `json:"head_img_url"`
	Count      int64  `json:"count"`
}

type CouponAlert struct {
	GoodsId   int64  `json:"goods_id"`
	Cover     string `json:"cover"`
	GoodsName string `json:"goods_name"`
	IsWin     bool   `json:"is_win"`
}

type CouponSource struct {
	Exchange int64 `json:"exchange"`
	Invite   int64 `json:"invite"`
	Game     int64 `json:"game"`
}

type NotifyStruct struct {
	OpenId    string `json:"open_id"`
	GoodsName string `json:"goods_name"`
	FormId    string `json:"form_id"`
	GoodsId   int64  `json:"goods_id"`
}

func CreateCoupon(userId, dlId, giftId, startAt, endAt int64, uniqueId string) (newCoupon *model.Coupon, err error) {
	coupon := &model.Coupon{
		UserId:     userId,
		UniqueId:   uniqueId,
		DlId:       dlId,
		GiftId:     giftId,
		QrCodeUrl:  "https://mp.leyougame.cc/img/1.jpg",
		QrCodeText: "https://mp.leyougame.cc/img/1.jpg",
		Status:     1,
		StartAt:    time.Now().Unix(),
		EndAt:      endAt,
	}
	if newCoupon, err = coupon.Insert(); err != nil {
		fmt.Printf("err %+v\n", err)
	}
	return
}

//抽奖逻辑及记录
func JoinCoupon(user *model.User, userExtra *model.UserExtra, goods *model.Goods, number int64) {
	go func() {
		generateCoupon(userExtra.UserId, goods.Id, int(number), 1)
		//消耗奖券
		expendCoupon(userExtra, number)
		//记录奖券消耗
		stringNumber := strconv.FormatInt(number, 10)
		floatNumber, _ := strconv.ParseFloat(stringNumber, 64)
		db.Mgo.WriteCoinsLog(user.Id, CONINS_EXPEND_COLLECT, "", "", "参与抽奖消耗", floatNumber)
		//记录待弹窗提示信息
		v := db.MainRedisClient.Exists(HOMEPAGE_ALERT_KEY)
		field := "user_" + strconv.FormatInt(user.Id, 10)
		if v.Val() == 1 {
			hv := db.MainRedisClient.HExists(HOMEPAGE_ALERT_KEY, field)
			if hv.Val() {
				hget := db.MainRedisClient.HGet(HOMEPAGE_ALERT_KEY, field)
				hgetVal := make([]int64, 0)
				json.Unmarshal([]byte(hget.Val()), &hgetVal)
				if !utils.Int64InSlice(hgetVal, goods.Id) {
					hgetVal = append(hgetVal, goods.Id)
					hgetJson, _ := json.Marshal(hgetVal)
					db.MainRedisClient.HSet(HOMEPAGE_ALERT_KEY, field, string(hgetJson))
				}
			} else {
				newSlice := []int64{goods.Id}
				jsonSlice, _ := json.Marshal(newSlice)
				db.MainRedisClient.HSet(HOMEPAGE_ALERT_KEY, field, string(jsonSlice))
			}
		} else {
			newSlice := []int64{goods.Id}
			jsonSlice, _ := json.Marshal(newSlice)
			db.MainRedisClient.HSet(HOMEPAGE_ALERT_KEY, field, string(jsonSlice))
		}
	}()
	cgl := new(model.UserGoodsLog)
	has, err := db.MysqlEngine.Where("user_id=? and goods_id=?", user.Id, goods.Id).Get(cgl)
	if !has && err == nil {
		if goods.LimitPeople-goods.CurPeople == 1 { //人满开奖
			go func() {
				GeneratePrize(goods)
			}()
			goods.CurPeople += 1
			goods.CouponStatus = 1
			goods.CouponAt = time.Now().Unix()
		} else { //普通记录人数
			goods.CurPeople += 1
		}
		if _, err := goods.Update(); err != nil {
			fmt.Printf("-----[JoinCoupon] err: %s", err)
		}
	}
	RecordUserCoupon(user, goods, number)
	return
}

//保存抽奖券
func generateCoupon(userId, goodsId int64, number int, source int64) {
	for i := 0; i < number; i++ {
		coupon := &model.GoodsCoupon{
			Code:    createCouponCode(),
			UserId:  userId,
			GoodsId: goodsId,
			Source:  source,
		}
		if _, err := coupon.Insert(); err != nil {
			fmt.Printf("-----[generateCoupon] err: %s", err)
		}
	}
}

//生成随机code
func createCouponCode() string {
	code := utils.GetRandomString(8)
	coupon := model.GetCouponByCode(code)
	if coupon != nil {
		createCouponCode()
	}
	return code
}

//消耗奖券
func expendCoupon(userExtra *model.UserExtra, number int64) {
	_, err := db.MysqlEngine.Exec("update user_extra set coupon = coupon-? where user_id=?", number, userExtra.UserId)
	if err != nil {
		fmt.Printf("-----[expendCoupon] err: %s", err)
	}
	return
}

//记录投注信息
func RecordUserCoupon(user *model.User, goods *model.Goods, number int64) {
	log := new(model.UserGoodsLog)
	has, _ := db.MysqlEngine.Where("user_id=? and goods_id=?", user.Id, goods.Id).Get(log)
	if has {
		log.CouponNum += number
		if _, err := log.Update(); err != nil {
			fmt.Printf("-----[recordUserCoupon] insert err: %s", err)
		}
	} else {
		newLog := &model.UserGoodsLog{
			Nickname:   base64.StdEncoding.EncodeToString([]byte(user.NickName)),
			HeadImgUrl: user.HeadImgUrl,
			UserId:     user.Id,
			GoodsId:    goods.Id,
			CouponNum:  number,
		}
		newLog.CouponNum = number
		if _, err := newLog.Insert(); err != nil {
			fmt.Printf("-----[recordUserCoupon] update err: %s", err)
		}
	}
	return
}

//随机抽取中奖券码
func GeneratePrize(goods *model.Goods) {
	var ugoArray []int64
	ugo := make([]model.UserGoodsLog, 0)
	err := db.MysqlEngine.Where("goods_id=?", goods.Id).Find(&ugo)
	if err != nil {
		fmt.Printf("-----err: %s", err)
	}
	if len(ugo) > 0 {
		for i := 0; i < len(ugo); i++ {
			ugoArray = append(ugoArray, ugo[i].UserId)
		}
	}
	sliceId := make([]model.GoodsCoupon, 0)
	db.MysqlEngine.In("user_id", ugoArray).Where("goods_id=? and status=?", goods.Id, 0).Find(&sliceId)
	fmt.Printf("sliceId-----sliceId :%v+", sliceId)
	if len(sliceId) > 0 {
		luckyId := make([]int64, 0)      //记录中奖券码id数组
		newSlice, _ := RandomId(sliceId) //打乱顺序的券码数组
		if goods.Num > 0 { //开奖次数大于0
			for i := 0; i < goods.Num; i++ {
				if len(newSlice) >= (i + 1) {
					choiseId := newSlice[i+1]
					goodsCoupon := new(model.GoodsCoupon)
					has, _ := db.MysqlEngine.Where("id=?", choiseId.Id).Get(goodsCoupon)
					if has {
						goodsCoupon.ExchangeAt = time.Now().Unix()
						goodsCoupon.Status = 1
						if _, err := goodsCoupon.Update(); err != nil {
							fmt.Printf("-----[generatePrize] err: %s", err)
						}
						luckyId = append(luckyId, choiseId.Id)
						go func() {
							NotifyLuckyUser(luckyId, goods.Title, goods.Id)
						}()
					}
				}
			}
			//将未中奖的券码状态更新为未中奖
			_, err = db.MysqlEngine.Table(new(model.GoodsCoupon)).NotIn("id", luckyId).Where("goods_id=?", goods.Id).Update(map[string]interface{}{"status": 2})
			if err != nil {
				fmt.Printf("-----[generatePrize] update goods_coupon status = 2 err: %s", err)
			}
		}
	}
	return
}

//通知中奖用户
func NotifyLuckyUser(userSlice []int64, goodsName string, goodsId int64) {
	notifySlice := make([]string, 0)
	notifyStruct := make([]NotifyStruct, 0)
	if len(userSlice) > 0 {
		for i := 0; i < len(userSlice); i++ {
			gc := new(model.GoodsCoupon)
			has, err := db.MysqlEngine.Where("id=?", userSlice[i]).Get(gc)
			if err != nil {
				fmt.Printf("-----[NotifyLuckyUser] err: %s", err)
			}
			if has {
				ugo := model.GetUgoByGameIdUserId(gc.UserId, "jiangbox")
				if ugo != nil {
					if !utils.StringInSlice(notifySlice, ugo.MiniOpenId) {
						notifySlice = append(notifySlice, ugo.MiniOpenId)
						curNotify := &NotifyStruct{
							OpenId:    ugo.MiniOpenId,
							GoodsName: goodsName,
							FormId:    GetUserFormId(ugo.UserId, goodsId),
							GoodsId:   goodsId,
						}
						notifyStruct = append(notifyStruct, *curNotify)
					}
				}
			}
		}
	}
	SendNotify(notifyStruct)
	return
}

//发送微信模版通知
func SendNotify(notifySlice []NotifyStruct) {
	jsonSlice, _ := json.Marshal(notifySlice)
	resp, err := http.PostForm("https://mp.leyougame.cc/wechat/notify",
		url.Values{"slice": {string(jsonSlice)}})
	if err != nil {
		err = fmt.Errorf("[GetUserQrscene]failed, err: %+v\n", err)
		fmt.Printf("[GetUserQrscene]failed, err: %+v\n", err)
		return
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		err = fmt.Errorf("[GetUserQrscene]failed, http.Status: %s", resp.Status)
		fmt.Printf("[GetUserQrscene]failed, http.Status: %s", resp.Status)
		return
	}
	_, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		err = fmt.Errorf("[GetUserQrscene]failed, err: %+v\n", err)
		fmt.Printf("[GetUserQrscene]failed, err: %+v\n", err)
		return
	}
	return
}

//打乱随机的slice
func RandomId(strings []model.GoodsCoupon) ([]model.GoodsCoupon, error) {
	rand.Seed(time.Now().Unix())
	for i := len(strings) - 1; i > 0; i-- {
		num := rand.Intn(i + 1)
		strings[i], strings[num] = strings[num], strings[i]
	}
	return strings, nil
}

//邀请用户获取抽奖券码奖励
func CreateInviteCoupon(userId int64, goods *model.Goods) {
	user := model.GetUserByUid(userId)
	//生成券码
	generateCoupon(userId, goods.Id, 1, 2)
	cgl := new(model.UserGoodsLog)
	has, err := db.MysqlEngine.Where("user_id=? and goods_id=?", user.Id, goods.Id).Get(cgl)
	if !has && err == nil {
		//判断是否开奖
		if goods.LimitPeople-goods.CurPeople == 1 { //人满开奖
			go func() {
				GeneratePrize(goods)
			}()
			goods.CurPeople += 1
			goods.CouponStatus = 1
			goods.CouponAt = time.Now().Unix()
		} else { //普通记录人数
			goods.CurPeople += 1
		}
		if _, err := goods.Update(); err != nil {
			fmt.Printf("-----[JoinCoupon] err: %s", err)
		}
	}
	//记录投注
	RecordUserCoupon(user, goods, 1)
	//记录待弹窗提示信息
	v := db.MainRedisClient.Exists(HOMEPAGE_ALERT_KEY)
	field := "user_" + strconv.FormatInt(user.Id, 10)
	if v.Val() == 1 {
		hv := db.MainRedisClient.HExists(HOMEPAGE_ALERT_KEY, field)
		if hv.Val() {
			hget := db.MainRedisClient.HGet(HOMEPAGE_ALERT_KEY, field)
			hgetVal := make([]int64, 0)
			json.Unmarshal([]byte(hget.Val()), &hgetVal)
			if !utils.Int64InSlice(hgetVal, goods.Id) {
				hgetVal = append(hgetVal, goods.Id)
				hgetJson, _ := json.Marshal(hgetVal)
				db.MainRedisClient.HSet(HOMEPAGE_ALERT_KEY, field, string(hgetJson))
			}
		} else {
			newSlice := []int64{goods.Id}
			jsonSlice, _ := json.Marshal(newSlice)
			db.MainRedisClient.HSet(HOMEPAGE_ALERT_KEY, field, string(jsonSlice))
		}
	} else {
		newSlice := []int64{goods.Id}
		jsonSlice, _ := json.Marshal(newSlice)
		db.MainRedisClient.HSet(HOMEPAGE_ALERT_KEY, field, string(jsonSlice))
	}
	//记录奖券来源
	db.Mgo.WriteCoinsLog(userId, CONINS_EARN_COLLECT, "", "", "邀请新用户奖励", 3)
	return
}

//获取我的抽奖记录
func GetMyCouponLog(user *model.User, pageNo, pageSize int) []CouponLog {
	reLog := make([]CouponLog, 0)
	logs := make([]model.UserGoodsLog, 0)
	curPageNo := (pageNo - 1) * pageSize
	err := db.MysqlEngine.Where("user_id=?", user.Id).Limit(pageSize, curPageNo).Desc("created_at").Find(&logs)
	if err != nil {
		fmt.Printf("-----[GetMyCouponLog] err: %s", err)
	}
	if len(logs) > 0 {
		for i := 0; i < len(logs); i++ {
			goods := model.GetGoodsById(logs[i].GoodsId)
			if goods != nil {
				curLog := &CouponLog{
					GoodsId:      logs[i].GoodsId,
					Cover:        utils.AddPrefix(goods.Cover),
					GoodsName:    goods.Title,
					CouponStatus: goods.CouponStatus,
					LimitPeople:  goods.LimitPeople,
					CurPeople:    goods.CurPeople,
					MyCouponNum:  logs[i].CouponNum,
					IsWin:        isWinCoupon(user, goods),
				}
				reLog = append(reLog, *curLog)
			}
		}
	}
	return reLog
}

//是否在本次活动中中奖
func isWinCoupon(user *model.User, goods *model.Goods) bool {
	goodsCoupon := new(model.GoodsCoupon)
	has, err := db.MysqlEngine.Where("goods_id=? and user_id=? and status=?", goods.Id, user.Id, 1).Get(goodsCoupon)
	if err != nil {
		fmt.Printf("-----[isWinCoupon] err: %s", err)
	}
	if has {
		return true
	}
	return false
}

//获取我的某次抽奖详情
func GetMyCouponDetail(user *model.User, goods *model.Goods) *CouponLog {
	totalCoupon, winCoupon := getMyCouponNumber(user, goods)
	couponLog := &CouponLog{
		GoodsId:      goods.Id,
		Cover:        utils.AddPrefix(goods.Cover),
		GoodsName:    goods.Title,
		CouponStatus: goods.CouponStatus,
		LimitPeople:  goods.LimitPeople,
		CurPeople:    goods.CurPeople,
		MyCouponNum:  int64(len(totalCoupon)),
		MyCoupon:     totalCoupon,
		MyWinCoupon:  winCoupon,
		IsWin:        isWinCoupon(user, goods),
	}
	return couponLog
}

//获取我的某次活动参与券码
func getMyCouponNumber(user *model.User, goods *model.Goods) ([]model.GoodsCoupon, []model.GoodsCoupon) {
	goodsCoupon := make([]model.GoodsCoupon, 0)
	err := db.MysqlEngine.Where("goods_id=? and user_id=?", goods.Id, user.Id).Find(&goodsCoupon)
	if err != nil {
		fmt.Printf("----[getMyCouponNumber] err: %s", err)
	}
	winCoupon := make([]model.GoodsCoupon, 0)
	err = db.MysqlEngine.Where("goods_id=? and user_id=? and status=?", goods.Id, user.Id, 1).Find(&winCoupon)
	if err != nil {
		fmt.Printf("----[getMyCouponNumber] err: %s", err)
	}
	return goodsCoupon, winCoupon
}

//获取活动参与人和中奖人信息
func GetCouponMember(goods *model.Goods) ([]CouponMember, []CouponMember) {
	totalMember := make([]CouponMember, 0)
	winMember := make([]CouponMember, 0)
	goodsCoupon := make([]model.GoodsCoupon, 0)
	err := db.MysqlEngine.Select("user_id").Where("goods_id=? and status=?", goods.Id, 1).GroupBy("user_id").Find(&goodsCoupon)
	if err != nil {
		fmt.Printf("-----[GetCouponMember] err: %s", err)
	}
	if len(goodsCoupon) > 0 {
		for i := 0; i < len(goodsCoupon); i++ {
			user := model.GetUserByUid(goodsCoupon[i].UserId)
			ugo := model.GetUserGoodsLog(goodsCoupon[i].UserId, goods.Id)
			if user != nil {
				curUser := &CouponMember{
					Nickname:   utils.DecodeNickName(user.NickName),
					HeadImgUrl: user.HeadImgUrl,
					Count:      ugo.CouponNum,
				}
				winMember = append(winMember, *curUser)
			}
		}
	}
	userGoodsLog := make([]model.UserGoodsLog, 0)
	err = db.MysqlEngine.Where("goods_id=?", goods.Id).OrderBy("created_at").Find(&userGoodsLog)
	if err != nil {
		fmt.Printf("-----[GetCouponMember] err: %s", err)
	}
	if len(userGoodsLog) > 0 {
		for i := 0; i < len(userGoodsLog); i++ {
			curUser := &CouponMember{
				Nickname:   utils.DecodeNickName(userGoodsLog[i].Nickname),
				HeadImgUrl: userGoodsLog[i].HeadImgUrl,
			}
			totalMember = append(totalMember, *curUser)
		}
	}
	return winMember, totalMember
}

//获取即将开奖的活动
func GetSoonCoupon(goodsId int64) []model.Goods {
	goods := make([]model.Goods, 0)
	err := db.MysqlEngine.Where("coupon_status = ? and  id <> ?", 0, goodsId).Limit(2).Find(&goods)
	if err != nil {
		fmt.Printf("-----[GetSoonCoupon] err: %s", err)
	}
	if len(goods) > 0 {
		for i := 0; i < len(goods); i++ {
			goods[i].Cover = utils.AddPrefix(goods[i].Cover)
		}
	}
	return goods
}

//获取用户的首页弹窗提示的抽奖信息
func GetMyCouponAlert(user *model.User) []CouponAlert {
	reSlice := make([]CouponAlert, 0)
	field := "user_" + strconv.FormatInt(user.Id, 10)
	exist := db.MainRedisClient.Exists(HOMEPAGE_ALERT_KEY)
	if exist.Val() == 1 {
		hexist := db.MainRedisClient.HExists(HOMEPAGE_ALERT_KEY, field)
		if hexist.Val() {
			hget := db.MainRedisClient.HGet(HOMEPAGE_ALERT_KEY, field)
			hgetSlice := make([]int64, 0)
			json.Unmarshal([]byte(hget.Val()), &hgetSlice)
			if len(hgetSlice) > 0 {
				newSlice := make([]int64, 0)
				for i := 0; i < len(hgetSlice); i++ {
					goods := model.GetGoodsById(hgetSlice[i])
					if goods != nil && goods.CouponStatus == 1 { //商品已开奖
						curSlice := &CouponAlert{
							GoodsId:   goods.Id,
							GoodsName: goods.Title,
							Cover:     utils.AddPrefix(goods.Cover),
							IsWin:     isWinCoupon(user, goods),
						}
						reSlice = append(reSlice, *curSlice)
						newSlice = utils.RemoveSliceElement(hgetSlice, goods.Id)
					}
				}
				newSliceJson, _ := json.Marshal(newSlice)
				db.MainRedisClient.HSet(HOMEPAGE_ALERT_KEY, field, string(newSliceJson))
			}
		}
	}
	return reSlice
}

//获取活动参与用户信息
func GoodsMembers(goods *model.Goods, pageNo, pageSize int64) []CouponMember {
	logs := make([]model.UserGoodsLog, 0)
	couponMember := make([]CouponMember, 0)
	curPageNo := (pageNo - 1) * pageSize
	err := db.MysqlEngine.SQL("select * from user_goods_log where goods_id=? order by coupon_num desc limit ?,?", goods.Id, curPageNo, pageSize).Find(&logs)
	if err != nil {
		fmt.Printf("-----[GoodsMembers] err: %s", err)
	}
	for i := 0; i < len(logs); i++ {
		curMember := &CouponMember{
			Nickname:   utils.DecodeNickName(logs[i].Nickname),
			HeadImgUrl: logs[i].HeadImgUrl,
			Count:      logs[i].CouponNum,
		}
		couponMember = append(couponMember, *curMember)
	}
	return couponMember
}

//获取我的抽奖券码来源记录
func MyCouponSource(userId, goodsId int64) CouponSource {
	coupon := new(model.GoodsCoupon)
	change, err := db.MysqlEngine.Where("user_id=? and goods_id=? and source=?", userId, goodsId, 1).Count(coupon)
	if err != nil {
		fmt.Printf("-----[MyCouponSource] err: %s", err)
	}
	invite, err := db.MysqlEngine.Where("user_id=? and goods_id=? and source=?", userId, goodsId, 2).Count(coupon)
	if err != nil {
		fmt.Printf("-----[MyCouponSource] err: %s", err)
	}
	game, err := db.MysqlEngine.Where("user_id=? and goods_id=? and source=?", userId, goodsId, 3).Count(coupon)
	if err != nil {
		fmt.Printf("-----[MyCouponSource] err: %s", err)
	}
	reStruct := &CouponSource{
		Exchange: change,
		Invite:   invite,
		Game:     game,
	}
	return *reStruct
}

//获取用户的通知formid
func GetUserFormId(userId, goodsId int64) string {
	key := FORM_ID_KEY
	field := "user_goods_form" + strconv.FormatInt(userId, 10) + "_" + strconv.FormatInt(goodsId, 10)
	exists := db.MainRedisClient.Exists(key)
	if exists.Val() == 1 {
		hexists := db.MainRedisClient.HExists(key, field)
		if hexists.Val() {
			hget := db.MainRedisClient.HGet(key, field)
			return hget.Val()
		}
	}
	return ""
}

//刷新用户的form_id
func RefreshUserFormId(user *model.User, goods *model.Goods, formId string) {
	key := FORM_ID_KEY
	field := "user_goods_form" + strconv.FormatInt(user.Id, 10) + "_" + strconv.FormatInt(goods.Id, 10)
	err := db.MainRedisClient.HSet(key, field, formId)
	if !err.Val() {
		fmt.Printf("RefreshUserFormId err: %s", err.String())
	}
	return
}

//FreeNumService: 判断是否参与过免费抽奖
func FreeNumService(user *model.User, goodsId string) (re bool) {
	var (
		freeKey string
		boolCmd *redis.BoolCmd
	)
	freeKey = FREE_LOTTERY_GOODS + goodsId
	if boolCmd = db.MainRedisClient.SIsMember(freeKey, user.UniqueId); boolCmd.Err() != nil {
		fmt.Printf("FreeNumService err : %s", boolCmd.Err().Error())
		return
	}
	if boolCmd.Val() {
		re = true
	}
	return
}

//FreeLotteryService: 免费抽奖
func FreeLotteryService(user *model.User, goodsId string) (err *utils.ErrorType) {
	var (
		extra   *model.UserExtra
		intCmd  *redis.IntCmd
		freeKey string
	)
	freeKey = FREE_LOTTERY_GOODS + goodsId
	extra = model.GetUserExtraByUid(user.Id)
	goodsId64, _ := strconv.ParseInt(goodsId, 10, 64)
	goods := model.GetGoodsById(goodsId64)
	if goods == nil {
		err = consts.ErrGoodsNotFound
		return
	}
	JoinCoupon(user, extra, goods, 1)
	if intCmd = db.MainRedisClient.SAdd(freeKey, user.UniqueId); intCmd.Err() != nil {
		err = consts.ErrInterval
		return
	}
	return
}
